<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.2.0">


  <link rel="apple-touch-icon" sizes="180x180" href="/myblog/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/myblog/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/myblog/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/myblog/images/logo.svg" color="#222">

<link rel="stylesheet" href="/myblog/css/main.css">



<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.1/css/all.min.css">
  <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/animate.css@3.1.1/animate.min.css">

<script class="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"kuang-yudi.gitee.io","root":"/myblog/","images":"/myblog/images","scheme":"Gemini","version":"8.1.0","exturl":false,"sidebar":{"position":"right","display":"post","padding":18,"offset":12},"copycode":false,"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":"gitalk","storage":true,"lazyload":false,"nav":null,"activeClass":"gitalk"},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"},"path":"/myblog/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false}};
  </script>
<meta name="description" content="父子组件通信、传值；页面间组件传值；动态组件；异步组件；vue中处理边界情况">
<meta property="og:type" content="article">
<meta property="og:title" content="vue组件">
<meta property="og:url" content="http://kuang-yudi.gitee.io/myblog/2021/01/08/vue%E7%BB%84%E4%BB%B6/index.html">
<meta property="og:site_name" content="KY迪的个人博客">
<meta property="og:description" content="父子组件通信、传值；页面间组件传值；动态组件；异步组件；vue中处理边界情况">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2021-01-08T02:37:46.000Z">
<meta property="article:modified_time" content="2021-01-11T05:32:49.428Z">
<meta property="article:author" content="匡宇迪">
<meta property="article:tag" content="组件">
<meta property="article:tag" content="父子组件传值">
<meta property="article:tag" content="父子组件通信">
<meta property="article:tag" content="页面间组件传值">
<meta property="article:tag" content="动态组件">
<meta property="article:tag" content="异步组件">
<meta property="article:tag" content="vue中处理边界情况">
<meta name="twitter:card" content="summary">


<link rel="canonical" href="http://kuang-yudi.gitee.io/myblog/2021/01/08/vue%E7%BB%84%E4%BB%B6/">


<script class="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>
<title>vue组件 | KY迪的个人博客</title>
  



  <noscript>
  <style>
  body { margin-top: 2rem; }

  .use-motion .menu-item,
  .use-motion .sidebar,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header {
    visibility: visible;
  }

  .use-motion .header,
  .use-motion .site-brand-container .toggle,
  .use-motion .footer { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle,
  .use-motion .custom-logo-image {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line {
    transform: scaleX(1);
  }

  .search-pop-overlay, .sidebar-nav { display: none; }
  .sidebar-panel { display: block; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/myblog/" class="brand" rel="start">
      <i class="logo-line"></i>
      <h1 class="site-title">KY迪的个人博客</h1>
      <i class="logo-line"></i>
    </a>
      <p class="site-subtitle" itemprop="description">个人技术博客</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu">
        <li class="menu-item menu-item-home"><a href="/myblog/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a></li>
        <li class="menu-item menu-item-tags"><a href="/myblog/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a></li>
        <li class="menu-item menu-item-categories"><a href="/myblog/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a></li>
        <li class="menu-item menu-item-archives"><a href="/myblog/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</div>
        
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>

  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <section class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-%E5%AD%90%E7%BB%84%E4%BB%B6%E8%B0%83%E7%94%A8%E7%88%B6%E7%BB%84%E4%BB%B6%E7%9A%84%E6%96%B9%E6%B3%95"><span class="nav-number">1.</span> <span class="nav-text">1. 子组件调用父组件的方法</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-1-this-parent-%E6%96%B9%E6%B3%95%E5%90%8D"><span class="nav-number">1.1.</span> <span class="nav-text">1.1 this.$parent.方法名</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-2-%E5%AD%90%E7%BB%84%E4%BB%B6%E4%B8%AD-emit-%E5%90%91%E7%88%B6%E7%BB%84%E4%BB%B6%E5%8F%91%E5%B0%84%E4%B8%80%E4%B8%AA%E4%BA%8B%E4%BB%B6%EF%BC%8C%E7%88%B6%E7%BB%84%E4%BB%B6%E7%9B%91%E5%90%AC%E6%AD%A4%E4%BA%8B%E4%BB%B6"><span class="nav-number">1.2.</span> <span class="nav-text">1.2 子组件中$emit()向父组件发射一个事件，父组件监听此事件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-3-%E7%88%B6%E7%BB%84%E4%BB%B6%E5%B0%86%E6%96%B9%E6%B3%95%E7%BB%91%E5%AE%9A%E7%BB%99%E5%AD%90%E7%BB%84%E4%BB%B6%E7%9A%84%E5%B1%9E%E6%80%A7%EF%BC%8C%E5%9C%A8%E5%AD%90%E7%BB%84%E4%BB%B6%E7%9A%84-props-%E4%B8%AD%E5%A3%B0%E6%98%8E%E6%AD%A4%E5%B1%9E%E6%80%A7%EF%BC%8C%E5%88%99%E7%88%B6%E7%BB%84%E4%BB%B6%E7%9A%84%E6%96%B9%E6%B3%95%E5%B0%B1%E4%BD%9C%E4%B8%BA%E5%AD%90%E7%BB%84%E4%BB%B6%E7%9A%84%E5%B1%9E%E6%80%A7%E5%9C%A8%E5%AD%90%E7%BB%84%E4%BB%B6%E4%B8%AD%E4%BD%BF%E7%94%A8%E3%80%82"><span class="nav-number">1.3.</span> <span class="nav-text">1.3 父组件将方法绑定给子组件的属性，在子组件的 props 中声明此属性，则父组件的方法就作为子组件的属性在子组件中使用。</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-%E7%88%B6%E7%BB%84%E4%BB%B6%E8%B0%83%E7%94%A8%E5%AD%90%E7%BB%84%E4%BB%B6%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%9Athis-refs-refName-%E5%AD%90%E7%BB%84%E4%BB%B6%E6%96%B9%E6%B3%95"><span class="nav-number">2.</span> <span class="nav-text">2. 父组件调用子组件的方法：this.$refs.refName.子组件方法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-%E7%88%B6%E5%AD%90%E7%BB%84%E4%BB%B6%E4%BC%A0%E5%80%BC"><span class="nav-number">3.</span> <span class="nav-text">3. 父子组件传值</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#3-1-%E7%88%B6%E4%BC%A0%E5%AD%90"><span class="nav-number">3.1.</span> <span class="nav-text">3.1 父传子</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-2-%E5%AD%90%E4%BC%A0%E7%88%B6"><span class="nav-number">3.2.</span> <span class="nav-text">3.2 子传父</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-%E9%A1%B5%E9%9D%A2%E9%97%B4%E7%BB%84%E4%BB%B6%E4%BC%A0%E5%80%BC"><span class="nav-number">4.</span> <span class="nav-text">4. 页面间组件传值</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-%E5%8A%A8%E6%80%81%E7%BB%84%E4%BB%B6"><span class="nav-number">5.</span> <span class="nav-text">5. 动态组件</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#5-1-%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8"><span class="nav-number">5.1.</span> <span class="nav-text">5.1 基本使用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5-2-keep-alive-%E4%B8%8E%E5%8A%A8%E6%80%81%E7%BB%84%E4%BB%B6%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-number">5.2.</span> <span class="nav-text">5.2 keep-alive 与动态组件的使用</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#6-%E5%BC%82%E6%AD%A5%E7%BB%84%E4%BB%B6"><span class="nav-number">6.</span> <span class="nav-text">6. 异步组件</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#6-1-%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF"><span class="nav-number">6.1.</span> <span class="nav-text">6.1 使用场景</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#6-2-%E4%BD%BF%E7%94%A8"><span class="nav-number">6.2.</span> <span class="nav-text">6.2 使用</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#7-vue-%E4%B8%AD%E5%A4%84%E7%90%86%E8%BE%B9%E7%95%8C%E6%83%85%E5%86%B5"><span class="nav-number">7.</span> <span class="nav-text">7. vue 中处理边界情况</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#7-1-%E8%AE%BF%E9%97%AE%E5%85%83%E7%B4%A0%E5%92%8C%E7%BB%84%E4%BB%B6"><span class="nav-number">7.1.</span> <span class="nav-text">7.1 访问元素和组件</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#7-1-1-%E8%AE%BF%E9%97%AE%E6%A0%B9%E5%AE%9E%E4%BE%8B-root"><span class="nav-number">7.1.1.</span> <span class="nav-text">7.1.1 访问根实例$root</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#7-1-2-%E8%AE%BF%E9%97%AE%E7%88%B6%E7%BB%84%E4%BB%B6%E5%AE%9E%E4%BE%8B-parent"><span class="nav-number">7.1.2.</span> <span class="nav-text">7.1.2 访问父组件实例$parent</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#7-1-3-%E8%AE%BF%E9%97%AE%E5%AD%90%E7%BB%84%E4%BB%B6-%E5%85%83%E7%B4%A0-refs"><span class="nav-number">7.1.3.</span> <span class="nav-text">7.1.3 访问子组件&#x2F;元素$refs</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#7-1-4-%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5"><span class="nav-number">7.1.4.</span> <span class="nav-text">7.1.4 依赖注入</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#7-2-%E7%A8%8B%E5%BA%8F%E5%8C%96%E7%9A%84%E4%BA%8B%E4%BB%B6%E4%BE%A6%E5%90%AC%E5%99%A8"><span class="nav-number">7.2.</span> <span class="nav-text">7.2 程序化的事件侦听器</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#7-3-%E5%BE%AA%E7%8E%AF%E5%BC%95%E7%94%A8"><span class="nav-number">7.3.</span> <span class="nav-text">7.3 循环引用</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#7-3-1-%E9%80%92%E5%BD%92%E7%BB%84%E4%BB%B6"><span class="nav-number">7.3.1.</span> <span class="nav-text">7.3.1 递归组件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#7-3-2-%E7%BB%84%E4%BB%B6%E9%97%B4%E5%BE%AA%E7%8E%AF%E5%BC%95%E7%94%A8"><span class="nav-number">7.3.2.</span> <span class="nav-text">7.3.2 组件间循环引用</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#8-%E5%85%84%E5%BC%9F%E7%BB%84%E4%BB%B6%E9%97%B4%E4%BC%A0%E5%80%BC"><span class="nav-number">8.</span> <span class="nav-text">8. 兄弟组件间传值</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#8-1-%E7%88%B6%E5%AD%90%E7%BB%84%E4%BB%B6%E5%8E%9F%E7%90%86"><span class="nav-number">8.1.</span> <span class="nav-text">8.1 父子组件原理</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#8-2-eventBus"><span class="nav-number">8.2.</span> <span class="nav-text">8.2 eventBus</span></a></li></ol></li></ol></div>
        </section>
        <!--/noindex-->

        <section class="site-overview-wrap sidebar-panel">
          <div class="site-author site-overview-item animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="匡宇迪"
      src="https://static.pptstore.net/picture/19/19/e1feb44f42cdf7e1202b_s.jpg">
  <p class="site-author-name" itemprop="name">匡宇迪</p>
  <div class="site-description" itemprop="description">用于记录学习web前端</div>
</div>
<div class="site-state-wrap site-overview-item animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/myblog/archives/">
        
          <span class="site-state-item-count">38</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/myblog/categories/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/myblog/tags/">
          
        <span class="site-state-item-count">87</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author site-overview-item animated">
      <span class="links-of-author-item">
        <a href="https://github.com/tonykyd/tonykyd.github.io" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;tonykyd&#x2F;tonykyd.github.io" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:1303665509@qq.com" title="E-Mail → mailto:1303665509@qq.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>



        </section>
      </div>
    </div>
  </aside>
  <div class="sidebar-dimmer"></div>


    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://kuang-yudi.gitee.io/myblog/2021/01/08/vue%E7%BB%84%E4%BB%B6/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="https://static.pptstore.net/picture/19/19/e1feb44f42cdf7e1202b_s.jpg">
      <meta itemprop="name" content="匡宇迪">
      <meta itemprop="description" content="用于记录学习web前端">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="KY迪的个人博客">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          vue组件
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2021-01-08 10:37:46" itemprop="dateCreated datePublished" datetime="2021-01-08T10:37:46+08:00">2021-01-08</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2021-01-11 13:32:49" itemprop="dateModified" datetime="2021-01-11T13:32:49+08:00">2021-01-11</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/myblog/categories/javascript/" itemprop="url" rel="index"><span itemprop="name">javascript</span></a>
        </span>
    </span>

  
    <span class="post-meta-item" title="阅读次数" id="busuanzi_container_page_pv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="far fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span id="busuanzi_value_page_pv"></span>
    </span>
</div>

            <div class="post-description">父子组件通信、传值；页面间组件传值；动态组件；异步组件；vue中处理边界情况</div>
        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
        <h2 id="1-子组件调用父组件的方法"><a href="#1-子组件调用父组件的方法" class="headerlink" title="1. 子组件调用父组件的方法"></a>1. 子组件调用父组件的方法</h2><h3 id="1-1-this-parent-方法名"><a href="#1-1-this-parent-方法名" class="headerlink" title="1.1 this.$parent.方法名"></a>1.1 this.$parent.方法名</h3><h3 id="1-2-子组件中-emit-向父组件发射一个事件，父组件监听此事件"><a href="#1-2-子组件中-emit-向父组件发射一个事件，父组件监听此事件" class="headerlink" title="1.2 子组件中$emit()向父组件发射一个事件，父组件监听此事件"></a>1.2 子组件中$emit()向父组件发射一个事件，父组件监听此事件</h3><p>解释：此时子组件中每次执行$emit 时都会调用父组件中此事件绑定的方法</p>
<h3 id="1-3-父组件将方法绑定给子组件的属性，在子组件的-props-中声明此属性，则父组件的方法就作为子组件的属性在子组件中使用。"><a href="#1-3-父组件将方法绑定给子组件的属性，在子组件的-props-中声明此属性，则父组件的方法就作为子组件的属性在子组件中使用。" class="headerlink" title="1.3 父组件将方法绑定给子组件的属性，在子组件的 props 中声明此属性，则父组件的方法就作为子组件的属性在子组件中使用。"></a>1.3 父组件将方法绑定给子组件的属性，在子组件的 props 中声明此属性，则父组件的方法就作为子组件的属性在子组件中使用。</h3><h2 id="2-父组件调用子组件的方法：this-refs-refName-子组件方法"><a href="#2-父组件调用子组件的方法：this-refs-refName-子组件方法" class="headerlink" title="2. 父组件调用子组件的方法：this.$refs.refName.子组件方法"></a>2. 父组件调用子组件的方法：this.$refs.refName.子组件方法</h2><p>ref 属性：为元素或子组件赋予一个引用,通过 this.$refs.refName 来访问元素或子组件的实例</p>
<hr>
<h2 id="3-父子组件传值"><a href="#3-父子组件传值" class="headerlink" title="3. 父子组件传值"></a>3. 父子组件传值</h2><h3 id="3-1-父传子"><a href="#3-1-父传子" class="headerlink" title="3.1 父传子"></a>3.1 父传子</h3><p>给子组件属性动态绑定父组件中数据，在子组件中用 props 声明此属性，则子组件中此属性的值为父组件中数据</p>
<h3 id="3-2-子传父"><a href="#3-2-子传父" class="headerlink" title="3.2 子传父"></a>3.2 子传父</h3><p>子组件中 this.$emit(‘自定义事件名’，传值)，父组件中监听此事件，绑定的方法的参数为子组件传过来的值</p>
<hr>
<h2 id="4-页面间组件传值"><a href="#4-页面间组件传值" class="headerlink" title="4. 页面间组件传值"></a>4. 页面间组件传值</h2><p>4.1 使用 vue-router 通过跳转链接带参数传参。</p>
<p>4.2 使用本地缓存 localStorge。</p>
<p>4.3 使用 vuex 数据管理传值。</p>
<hr>
<h2 id="5-动态组件"><a href="#5-动态组件" class="headerlink" title="5. 动态组件"></a>5. 动态组件</h2><h3 id="5-1-基本使用"><a href="#5-1-基本使用" class="headerlink" title="5.1 基本使用"></a>5.1 基本使用</h3><p>多个组件通过同一个挂载点进行组件的切换，动态绑定的 is 属性的值是哪个组件的名称，那么页面就会显示哪个组件。</p>
<p><strong>扩展</strong>：is 属性：指定组件名字渲染此标签(所以可以用来解决标签内只能出现指定子标签的渲染问题——用指定标签名加 is 绑定自定义组件名)<br>例：table 标签中只能渲染 tr 标签，不能直接渲染自定义组件，用 is 属性解决此问题</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;table&gt;</span><br><span class="line">  &lt;tr is&#x3D;&quot;myComponentName&quot;&gt;&lt;&#x2F;tr&gt;</span><br><span class="line">&lt;&#x2F;table&gt;</span><br></pre></td></tr></table></figure>

<h3 id="5-2-keep-alive-与动态组件的使用"><a href="#5-2-keep-alive-与动态组件的使用" class="headerlink" title="5.2 keep-alive 与动态组件的使用"></a>5.2 keep-alive 与动态组件的使用</h3><p><strong>原理</strong>：动态组件在切换过程中会重复组建的销毁、创建。</p>
<p><strong>keep-alive 作用</strong>：保持这些组件的状态(缓存创建的组件)，以避免反复重渲染导致的性能问题，所以在切换回组件时，用的是缓存的组件，也能保持组件在失活前(切换前)的状态</p>
<h2 id="6-异步组件"><a href="#6-异步组件" class="headerlink" title="6. 异步组件"></a>6. 异步组件</h2><h3 id="6-1-使用场景"><a href="#6-1-使用场景" class="headerlink" title="6.1 使用场景"></a>6.1 使用场景</h3><p>当组件太多时，一次性加载所有组件导致卡顿、内存消耗太大，所以需要异步组件：只有在要渲染时加载对应的组件。</p>
<h3 id="6-2-使用"><a href="#6-2-使用" class="headerlink" title="6.2 使用"></a>6.2 使用</h3><p>用工厂函数实现动态导入：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">const myComponent&#x3D; () &#x3D;&gt; import(&#39;.&#x2F;my-async-component&#39;)</span><br></pre></td></tr></table></figure>

<p>解释：只有在渲染到此组件时，函数才会开始执行，加载此组件</p>
<hr>
<h2 id="7-vue-中处理边界情况"><a href="#7-vue-中处理边界情况" class="headerlink" title="7. vue 中处理边界情况"></a>7. vue 中处理边界情况</h2><h3 id="7-1-访问元素和组件"><a href="#7-1-访问元素和组件" class="headerlink" title="7.1 访问元素和组件"></a>7.1 访问元素和组件</h3><p>绝大多数情况下，我们最好不要触达另一个组件实例内部或手动操作 DOM 元素。不过也确实在一些情况下做这些事情是合适的。</p>
<h4 id="7-1-1-访问根实例-root"><a href="#7-1-1-访问根实例-root" class="headerlink" title="7.1.1 访问根实例$root"></a>7.1.1 访问根实例$root</h4><p>使用：通过$root 拿到根组件进行访问和使用。<br>缺点：不能确定根组件中的数据是谁修改的。<br>推荐用 vuex 来管理公共数据。</p>
<h4 id="7-1-2-访问父组件实例-parent"><a href="#7-1-2-访问父组件实例-parent" class="headerlink" title="7.1.2 访问父组件实例$parent"></a>7.1.2 访问父组件实例$parent</h4><p>使用：通过$parent 拿到父组件中的数据/方法进行使用。<br>缺点：<br>① 同样不能确定父组件中的数据是谁修改的。<br>② 同时，如果父组件与子组件间层级发生变化，就会不好控制(组件层级的深度的变化会导致问题：比如说父子组件变成爷孙组件，那么子组件中this.$parent 的指向就错了)<br>推荐使用<strong>依赖注入</strong></p>
<h4 id="7-1-3-访问子组件-元素-refs"><a href="#7-1-3-访问子组件-元素-refs" class="headerlink" title="7.1.3 访问子组件/元素$refs"></a>7.1.3 访问子组件/元素$refs</h4><p>缺点：$refs 只会在组件渲染完成之后(mounted)生效，并且它们不是响应式的。这仅作为一个用于直接操作子组件的“逃生舱”——你应该避免在模板或计算属性中访问 $refs。</p>
<h4 id="7-1-4-依赖注入"><a href="#7-1-4-依赖注入" class="headerlink" title="7.1.4 依赖注入"></a>7.1.4 依赖注入</h4><p>作用：解决父组件和子组件的层级不确定导致子组件访问父组件的问题</p>
<p>使用：在父组件中提供 provide 指定提供给后代组件的数据/方法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">provide: function () &#123;</span><br><span class="line">  return &#123;</span><br><span class="line">    getMap: this.getMap &#x2F;&#x2F; getMap为方法名</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>任何后代组件里，我们都可以使用 inject 选项来接收指定的我们想要添加在这个实例上的 property：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">inject: [&#39;getMap&#39;]</span><br></pre></td></tr></table></figure>

<p><strong>总结</strong>：依赖注入还是有负面影响的。它将你应用程序中的组件与它们当前的组织方式耦合起来，使重构变得更加困难。同时所提供的 property 是非响应式的。这是出于设计的考虑，因为使用它们来创建一个中心化规模化的数据跟使用 $root 做这件事都是不够好的。如果你想要共享的这个 property 是你的应用特有的，而不是通用化的，或者如果你想在祖先组件中更新所提供的数据，那么这意味着你可能需要换用一个像 Vuex 这样真正的状态管理方案了。</p>
<hr>
<h3 id="7-2-程序化的事件侦听器"><a href="#7-2-程序化的事件侦听器" class="headerlink" title="7.2 程序化的事件侦听器"></a>7.2 程序化的事件侦听器</h3><p>$emit 可以被 v-on 侦听， Vue 实例同时在其事件接口中提供了其它的方法。</p>
<p>我们可以：<br>通过 $on(eventName, eventHandler) 侦听一个事件<br>通过 $once(eventName, eventHandler) 一次性侦听一个事件<br>通过 $off(eventName, eventHandler) 停止侦听一个事件</p>
<p><strong>使用场景</strong>：在一个组件实例上手动侦听事件(将原本在不同生命钩子中执行的建立代码和销毁代码通过事件侦听放在一起，减少了代码量即程序化处理代码)</p>
<p><strong>解释下列代码</strong>：picker 的销毁本来在生命钩子 beforeDestroy 中执行，但是那样每个创建的 picker 都要有对应的销毁代码，现在可以通过 this.$once 监听生命钩子的触发来执行销毁，减少了代码量(更程序化的处理代码)</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">mounted: function () &#123;</span><br><span class="line">  this.attachDatepicker(&#39;startDateInput&#39;)</span><br><span class="line">  this.attachDatepicker(&#39;endDateInput&#39;)</span><br><span class="line">&#125;,</span><br><span class="line">methods: &#123;</span><br><span class="line">  attachDatepicker: function (refName) &#123;</span><br><span class="line">    var picker &#x3D; new Pikaday(&#123;</span><br><span class="line">      field: this.$refs[refName],</span><br><span class="line">      format: &#39;YYYY-MM-DD&#39;</span><br><span class="line">    &#125;)</span><br><span class="line"></span><br><span class="line">    this.$once(&#39;hook:beforeDestroy&#39;, function () &#123;</span><br><span class="line">      picker.destroy()</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>注：如果不得不在单个组件里做很多建立和清理的工作，最好的方式通常还是创建更多的模块化组件</p>
<hr>
<h3 id="7-3-循环引用"><a href="#7-3-循环引用" class="headerlink" title="7.3 循环引用"></a>7.3 循环引用</h3><h4 id="7-3-1-递归组件"><a href="#7-3-1-递归组件" class="headerlink" title="7.3.1 递归组件"></a>7.3.1 递归组件</h4><p><strong>使用：</strong>在组件自身的模板 template 中调用自己，同时必须在 name 中声明此组件的名字。通过 props 拿到父组件数据，在模板中调用自己时再次动态绑定此属性，将次级数据传入，形成递归，判断 v-if 为 false 时停止渲染结束递归。</p>
<p><strong>应用场景：</strong>同一组件渲染每层数据</p>
<p>例：props 中拿到父组件中的 list 数据，name 中声明此组件的名字，模板中调用自身组件标签，再次绑定 list 属性，传入次级数据，直到 v-if 判断为 false 停止渲染，结束递归。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line"></span><br><span class="line">  &lt;ul&gt;</span><br><span class="line">    &lt;li v-for&#x3D;&quot;(item,index) in list&quot; :key&#x3D;&quot;index&quot;&gt;</span><br><span class="line">      &lt;tree-menus v-if&#x3D;&quot;isboolean()&quot; :list&#x3D;&quot;item.cList&quot;&gt;&lt;&#x2F;tree-menus&gt;</span><br><span class="line">    &lt;&#x2F;li&gt;</span><br><span class="line">  &lt;&#x2F;ul&gt;</span><br><span class="line"></span><br><span class="line">&lt;&#x2F;template&gt;</span><br><span class="line">&lt;script&gt;</span><br><span class="line">export default &#123;</span><br><span class="line">  name: &#39;treeMenus&#39;,</span><br><span class="line">  props: &#123;</span><br><span class="line">    list: listData</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;&#x2F;script&gt;</span><br></pre></td></tr></table></figure>

<hr>
<h4 id="7-3-2-组件间循环引用"><a href="#7-3-2-组件间循环引用" class="headerlink" title="7.3.2 组件间循环引用"></a>7.3.2 组件间循环引用</h4><p><strong>使用：</strong>组件互为对方的后代和祖先元素(即互相嵌套)<br>例：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; &lt;tree-folder&gt;组件：</span><br><span class="line">&lt;p&gt;</span><br><span class="line">  &lt;span&gt;&#123;&#123; folder.name &#125;&#125;&lt;&#x2F;span&gt;</span><br><span class="line">  &lt;tree-folder-contents :children&#x3D;&quot;folder.children&quot;&#x2F;&gt;</span><br><span class="line">&lt;&#x2F;p&gt;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; &lt;tree-folder-contents&gt;组件：</span><br><span class="line">&lt;ul&gt;</span><br><span class="line">  &lt;li v-for&#x3D;&quot;child in children&quot;&gt;</span><br><span class="line">    &lt;tree-folder v-if&#x3D;&quot;child.children&quot; :folder&#x3D;&quot;child&quot;&#x2F;&gt;</span><br><span class="line">    &lt;span v-else&gt;&#123;&#123; child.name &#125;&#125;&lt;&#x2F;span&gt;</span><br><span class="line">  &lt;&#x2F;li&gt;</span><br><span class="line">&lt;&#x2F;ul&gt;</span><br></pre></td></tr></table></figure>

<p><strong>应用场景：</strong>构建一个文件目录树，类似资源管理器那样的</p>
<p><strong>解决此问题：</strong><br><strong>场景一：</strong><br>全局注册时，vue 中自动处理。<br><strong>场景二：</strong><br>本地注册时，异步导入(异步组件)，也能自动处理。<br><strong>场景三：</strong><br>模块系统依赖/导入组件时，给模块系统一个点，在那里 A 反正是需要 B 的，但是我们不需要先解析 B。即先解析指定的组件不管另一个。<br>例：在 tree-folder 的生命钩子中导入 tree-folder-contents 组件(类似异步加载组件)</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">beforeCreate: function () &#123;</span><br><span class="line">  this.$options.components.TreeFolderContents &#x3D; require(&#39;.&#x2F;tree-folder-contents.vue&#39;).default</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<hr>
<h2 id="8-兄弟组件间传值"><a href="#8-兄弟组件间传值" class="headerlink" title="8. 兄弟组件间传值"></a>8. 兄弟组件间传值</h2><h3 id="8-1-父子组件原理"><a href="#8-1-父子组件原理" class="headerlink" title="8.1 父子组件原理"></a>8.1 父子组件原理</h3><p>兄弟 A 组件传给父组件，父组件传给兄弟 B 组件</p>
<h3 id="8-2-eventBus"><a href="#8-2-eventBus" class="headerlink" title="8.2 eventBus"></a>8.2 eventBus</h3><p>原理：创建一个暴露 vue 实例的 js 文件，组件中引入此 js 文件，兄弟 A 通过此 vue 实例的$emit发射自定义事件及数据，兄弟B通过此vue实例的$on 接收自定义事件及数据。</p>

    </div>

    
    
    

    <footer class="post-footer">
          <div class="followme">
  <span>欢迎关注我的其它发布渠道</span>

  <div class="social-list">

      <div class="social-item">
        <a target="_blank" class="social-link" href="/myblog/images/wechat_channel.jpg">
          <span class="icon">
            <i class="fab fa-weixin"></i>
          </span>

          <span class="label">WeChat</span>
        </a>
      </div>
  </div>
</div>

          <div class="post-tags">
              <a href="/myblog/tags/%E7%BB%84%E4%BB%B6/" rel="tag"># 组件</a>
              <a href="/myblog/tags/%E7%88%B6%E5%AD%90%E7%BB%84%E4%BB%B6%E4%BC%A0%E5%80%BC/" rel="tag"># 父子组件传值</a>
              <a href="/myblog/tags/%E7%88%B6%E5%AD%90%E7%BB%84%E4%BB%B6%E9%80%9A%E4%BF%A1/" rel="tag"># 父子组件通信</a>
              <a href="/myblog/tags/%E9%A1%B5%E9%9D%A2%E9%97%B4%E7%BB%84%E4%BB%B6%E4%BC%A0%E5%80%BC/" rel="tag"># 页面间组件传值</a>
              <a href="/myblog/tags/%E5%8A%A8%E6%80%81%E7%BB%84%E4%BB%B6/" rel="tag"># 动态组件</a>
              <a href="/myblog/tags/%E5%BC%82%E6%AD%A5%E7%BB%84%E4%BB%B6/" rel="tag"># 异步组件</a>
              <a href="/myblog/tags/vue%E4%B8%AD%E5%A4%84%E7%90%86%E8%BE%B9%E7%95%8C%E6%83%85%E5%86%B5/" rel="tag"># vue中处理边界情况</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/myblog/2021/01/07/vue%E8%AF%AD%E6%B3%95/" rel="prev" title="vue语法">
                  <i class="fa fa-chevron-left"></i> vue语法
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/myblog/2021/01/08/vue%E8%B7%AF%E7%94%B1%E2%80%94Vue%20Router/" rel="next" title="vue路由—Vue Router">
                  vue路由—Vue Router <i class="fa fa-chevron-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






    <div class="comments" id="gitalk-container"></div>

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      const activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      const commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>
</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 
  <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">匡宇迪</span>
</div>
<div class="busuanzi-count">
    <span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>

    </div>
  </footer>

  
  <script src="//cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js"></script>
<script src="/myblog/js/utils.js"></script><script src="/myblog/js/motion.js"></script><script src="/myblog/js/next-boot.js"></script>

  
<script src="/myblog/js/local-search.js"></script>






  
  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>






<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/gitalk@1.7.0/dist/gitalk.css">

<script>
NexT.utils.loadComments('#gitalk-container', () => {
  NexT.utils.getScript('//cdn.jsdelivr.net/npm/gitalk@1.7.0/dist/gitalk.min.js', () => {
    var gitalk = new Gitalk({
      clientID    : '1926f8a1c453a1121d8d',
      clientSecret: '426722f9eef7599f8ebb3220379e704ea007a5f2',
      repo        : '',
      owner       : '',
      admin       : [''],
      id          : 'c07542d9cff9fbcddd2870ed3c7c75ca',
        language: '',
      distractionFreeMode: true
    });
    gitalk.render('gitalk-container');
  }, window.Gitalk);
});
</script>

</body>
</html>
